package com.chaucer.utils;


import com.mysql.cj.util.StringUtils;

public class GenericTokenParser {

    private final String openToken;
    private final String closeToken;
    private final TokenHandler handler;

    public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
        this.openToken = openToken;
        this.closeToken = closeToken;
        this.handler = handler;
    }

    public String parse(String text) {
        if (StringUtils.isNullOrEmpty(text)) {
            return "";
        }
        int start = text.indexOf(openToken, 0);
        if (start == -1) {
            return text;
        }
        char[] src = text.toCharArray();
        int offset = 0;
        final StringBuilder builder = new StringBuilder();
        StringBuilder expression = null;
        while (start > -1) {
            if (start > 0 && src[start - 1] == '\\') {
                builder.append(src, offset, start - offset - 1).append(openToken);
                offset = start + openToken.length();
            } else {
                int end = text.indexOf(closeToken, start);
                if (end == -1) {//如果不存在openToken，则直接将offset位置后的字符添加到builder中
                    builder.append(src, offset, src.length - offset);
                    offset = src.length;//重设offset
                } else {
                    builder.append(src, offset, start - offset);//添加openToken前offset后位置的字符到bulider中
                    offset = start + openToken.length();//重设offset
                    String content = new String(src, offset, end - offset);//获取openToken和endToken位置间的字符串
                    builder.append(handler.handleToken(content));//调用handler进行处理
                    offset = end + closeToken.length();//重设offset
                }
            }
            start = text.indexOf(openToken, offset);//开始下一个循环
        }
        //只有当text中不存在openToken且text.length大于0时才会执行下面的语句
        if (offset < src.length) {
            builder.append(src, offset, src.length - offset);
        }
        return builder.toString();
    }
}
